package com.fabula.android.timeline.XMPP;



import java.util.*;

import android.accounts.Account;
import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.fabula.android.timeline.TimelineActivity;
import com.fabula.android.timeline.database.DatabaseHelper;
import com.fabula.android.timeline.database.TimelineDatabaseHelper;
import com.fabula.android.timeline.database.contentmanagers.ContentAdder;
import com.fabula.android.timeline.database.contentmanagers.ContentLoader;
import com.fabula.android.timeline.models.*;
import com.fabula.android.timeline.utilities.Constants;

/**
 * Class that interfaces between the XMPP connection and the rest of the app
 * @author Mads
 *
 */
public class XMPPManager{

	private static void log(Object arg){
		//Log.i("XMPPMANAGER",arg.toString());
	}

	@SuppressWarnings("unused")
	private static void err(Object arg){
		//Log.i("XMPPMANAGER ERROR",arg.toString());
	}

	/*
	 * Static convenience...
	 */
	public static TimelineActivity current;
	private static XMPPListener listener;
	private static Thread XMPPThread;
	private static Handler handler;
	public static Context context;
	

	/**
	 * Sets what handlet this class will use to communicate with the view
	 * @param handler
	 */
	public static void setHandler(Handler handler){
		XMPPManager.handler = handler;
	}
	
	/**
	 * Sets the current context
	 * @param context
	 */
	public static void setContext(Context context){
		XMPPManager.context = context;
	}

	/**
	 * Update to current TimelineActivity.
	 */
	public static void setTimelineActivity(TimelineActivity timelineActivity){
		current = timelineActivity;
	}

	/**
	 * Initializes the XMPP connection, logging in with the given user.
	 * @param user
	 */
	public static void XMPPInit(User user){
		XMPPThread = new Thread(listener = new XMPPListener(user));
		XMPPThread.start();
		try {
			XMPPThread.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log("Finished XMPP init");
	}
	
	
	public static boolean isConnectedToXmppServer(){
		return listener.isConectedToXmppServer();
	}
	
	/**
	 * Stores a given item in the database.
	 * Called by the listener.
	 * 
	 * @param item the item to be stored
	 * @param toEvent the event it belongs to
	 * @param toTimeline the itemline it belongs to
	 * @param creator the creator of the item
	 */
	public static void storeItem(EventItem item, String toEvent,
			String toTimeline, String creator) {
		boolean newEvent = false;

		ContentLoader cl = new ContentLoader(context.getApplicationContext());
		new TimelineDatabaseHelper(context, Constants.ALL_TIMELINES_DATABASE_NAME);
		new DatabaseHelper(context.getApplicationContext(),cl.getExperienceById(toTimeline).getTitle()+".db");
		ContentAdder ca = new ContentAdder(context.getApplicationContext());

		BaseEvent event = cl.getEventByID(toEvent);
		if(event == null){
			event = new Event(toEvent, toTimeline, new Date(System.currentTimeMillis()), null, new Account(creator, "com.google"));
			event.setCreatorName(creator);
			event.setShared(true);
			ca.addEventToEventContentProvider(event);
			newEvent = true;
		}
		ca.addEventItemToEventContentProviderIfEventAlreadyExists((Event)event, item);
		((Event)event).addEventItem(item);

		if(current!=null && handler != null){
			if(current.getTimeline().getId().equals(toTimeline)){
				if(!newEvent){
					((Event)current.getTimeline().getEvent(toEvent)).addEventItem(item);
					updateTimeline();
					log("Added event item to event");
				}
				else {
					current.getTimeline().addEvent(event);
					updateTimeline(event);
					log("Added the new event to the timeline");
				}
			}
		}
	}

	/**
	 * Stores a given emotion in the database.
	 * Called by the listener.
	 * 
	 * @param emo the emotion to be stored
	 * @param toEvent the event it belongs to
	 * @param toTimeline the itemline it belongs to
	 * @param creator the creator of the item
	 */
	public static void storeItem(Emotion emo, String toEvent,
			String toTimeline, String creator) {
		boolean newEvent = false;
		ContentLoader cl = new ContentLoader(context.getApplicationContext());
		new TimelineDatabaseHelper(context, Constants.ALL_TIMELINES_DATABASE_NAME);
		new DatabaseHelper(context.getApplicationContext(),cl.getExperienceById(toTimeline).getTitle()+".db");
		ContentAdder ca = new ContentAdder(context.getApplicationContext());

		BaseEvent event = cl.getEventByID(toEvent);

		if(event == null){
			event = new Event(toEvent, toTimeline, new Date(System.currentTimeMillis()), null, new Account(creator, "com.google"));
			event.setCreatorName(creator);
			ca.addEventToEventContentProvider(event);
			newEvent = true;
		}
		ca.addEmotionToDatabase(null, emo);
		cl.addEmotionToEvent((Event)event, emo.getEmotionid());


		if(current!=null && handler != null){
			if(current.getTimeline().getId().equals(toTimeline)){
				if(newEvent)updateTimeline(event);
				else {
					if(!newEvent)((Event)current.getTimeline().getEvent(toEvent)).addEmotion(emo);
					updateTimeline();
				}
			}
		}
	}
	
	/**
	 * Updates the timeline with the given event
	 * @param event
	 */
	private static void updateTimeline(BaseEvent event){
		android.os.Message message = new android.os.Message();
		message.what = 2;
		message.obj = event;
		handler.sendMessage(message);
	}
	/**
	 * Updates the timeline
	 */
	private static void updateTimeline(){
		android.os.Message message = new android.os.Message();
		message.what = 1;
		handler.sendMessage(message);
	}
	
	/**
	 * Stores the given timeline in the database. Calld by the listener.
	 * @param timeline
	 */
	public static void storeItem(Experience timeline) {
		new TimelineDatabaseHelper(context, Constants.ALL_TIMELINES_DATABASE_NAME);
		new ContentAdder(context.getApplicationContext()).addExperienceToTimelineContentProvider(timeline);

		log("Fetched "+timeline);
		log("It contains the following:");
		for(BaseEvent event: timeline.getEvents()){
			log("Event: "+event.getId());
			for(EventItem item: event.getEventItems()){
				log("Item: "+item.getId());
			}
		}
	}
	
	/**
	 * Stores a given mood in the database.
	 * Called by the listener.
	 * 
	 * @param mood the mood to be stored
	 * @param toTimeline the itemline it belongs to
	 * @param creator the creator of the item
	 */
	public static void storeItem(MoodEvent mood, String toTimeline,
			String creator) {
		ContentLoader cl = new ContentLoader(context.getApplicationContext());
		new TimelineDatabaseHelper(context, Constants.ALL_TIMELINES_DATABASE_NAME);
		new DatabaseHelper(context.getApplicationContext(),cl.getExperienceById(toTimeline).getTitle()+".db");
		ContentAdder ca = new ContentAdder(context.getApplicationContext());


		ca.addEventToEventContentProvider(mood);


		if(current!=null && handler != null){
			if(current.getTimeline().getId().equals(toTimeline)){
				updateTimeline(mood);
			}
		}
	}
	/**
	 * Share a new event with other members of the timeline.
	 * 
	 * @param event the event to be shared
	 * @param target other members of the timeline
	 */
	public static void shareEvent(BaseEvent event, Experience experience){
		listener.shareEvent(event, experience);
	}

	/**
	 * Share a timeline with the other members of the timeline.
	 * 
	 * @param timeline the timeline to be shared
	 */
	public static void shareTimeline(Experience timeline) {
		listener.shareTimeline(timeline);
	}
	
	/**
	 * Share a timeline with the other members of the timeline.
	 * @param note the note to be shared
	 * @param event the event it belongs to
	 * @param experience the timeline it belongs to
	 */
	public static void shareEventItem(EventItem note, Event event,
			Experience experience) {
		listener.shareEventItem(note, event, experience);
	}
	
	/**
	 * Share an emotion with the other members of the timeline
	 * @param emo the emotion to be shared
	 * @param event the event it belongs to
	 * @param experience the timeline it belongs to
	 */
	public static void shareEmotion(Emotion emo, Event event,
			Experience experience) {
		listener.shareEmotion(emo, event, experience);
	}
	
	/**
	 * Share an event with the other members of the timeline
	 * @param event the event to be shared
	 */
	public static void shareEvent(Event event) {
		listener.shareEvent(event, current.getTimeline());
	}
	
	/**
	 * Adds an event to the database under the presumption that the database is already opened.
	 * The presumption is made by the PubSub manager when creating the CroMAR timeline,
	 * at which point the presumption is safe to make and speeds up the creation.
	 * @param event
	 */
	public static void putEventPresumeOpenDB(Event event) {
		ContentAdder ca = new ContentAdder(context.getApplicationContext());
		ca.addEventToEventContentProvider(event);
	}
	
	/**
	 * Adds an event to the database
	 * called by the listener
	 * @param event
	 */
	public static void putEvent(Event event) {

		new DatabaseHelper(context.getApplicationContext(),Constants.CroMAR_TIMELINE_TITLE+".db");
		ContentAdder ca = new ContentAdder(context.getApplicationContext());
		ca.addEventToEventContentProvider(event);
		if(current!=null && handler != null){
			if(current.getTimeline().getId().equals(event.getExperienceid())){
				updateTimeline(event);
			}
		}
	}
}